#ifndef  FRAME_INTERFACE_H
#define  FRAME_INTERFACE_H


#include <cstddef>
#include <cstring>
#include <string>
#include <memory>

namespace frame {

class IRunnable { //common base 
public:
    typedef std::shared_ptr<IRunnable> Ptr;

    virtual ~IRunnable(){}

    virtual uint64_t getId() const = 0;
    virtual void setId(const uint64_t id) = 0;

    virtual bool isOpen() = 0;
    virtual int open() = 0;
    virtual void close() = 0;
};

class IChannelHandlerAdapter;
class ChannelImpl;
class IChannel :public IRunnable{
public:
    typedef std::shared_ptr<IChannel> Ptr;

    virtual ~IChannel(){}

    int write(const char * str) {
        return write(str, strlen(str));
    }
    virtual int write(const char * buf, int size) = 0; 
    virtual int write(const std::string & str) = 0;

    virtual int disconnect() = 0;

    virtual const std::string & getRemoteIp() = 0;
    virtual const int getRemotePort() = 0;

    virtual const std::string & getLocalIp() = 0;
    virtual const int getLocalPort() = 0;

    virtual bool isConnected() const = 0;
    virtual void setConnected(bool connected) = 0;

    virtual void setImpl(std::shared_ptr<ChannelImpl> channelImpl) = 0;

    virtual std::shared_ptr<IChannelHandlerAdapter> getHandlerAdapter() const = 0;
};

class IChannelHandlerAdapter {
public:
    typedef std::shared_ptr<IChannelHandlerAdapter> Ptr;

    virtual ~IChannelHandlerAdapter(){}

    virtual void connected(IChannel::Ptr channel) = 0;
    virtual void connectFailed(IChannel::Ptr channel, int error) = 0;

    virtual void disconnected(IChannel::Ptr channel, int error) = 0;

    virtual void read(IChannel::Ptr channel, const char * buf,  std::size_t size) = 0;
    virtual void readException(IChannel::Ptr channel, int error) = 0 ;

    virtual void writed(IChannel::Ptr channel, std::size_t size) = 0 ;
    virtual void writeException(IChannel::Ptr channel, int error) = 0;
};




class IClient : public IRunnable{
public:
    typedef std::shared_ptr<IClient> Ptr;
    virtual ~IClient(){}

    IChannel::Ptr connect(const std::string & remoteIp, const int remotePort){
        return connect(remoteIp, remotePort, nullptr);
    }
    virtual IChannel::Ptr connect(const std::string & remoteIp, const int remotePort, IChannelHandlerAdapter::Ptr channelHandler) = 0;

    virtual IChannelHandlerAdapter::Ptr getDefaultChannelHandlerAdapter() = 0;

    virtual uint64_t add(IChannel::Ptr runnable) = 0;
    virtual IChannel::Ptr get(uint64_t id) = 0;
    virtual void remove(uint64_t id) = 0;
    virtual size_t size() = 0;

};


class ServiceImpl;
class ImplFactory;
class IService {
public:
    typedef std::shared_ptr<IService> Ptr;

    virtual ~IService(){}

    virtual int start() = 0;
    virtual int run() = 0;
    virtual void stop() = 0;

    virtual uint64_t add(IRunnable::Ptr runnable) = 0;
    virtual IRunnable::Ptr get(uint64_t id) = 0;
    virtual void remove(uint64_t id) = 0;
    virtual size_t size() = 0;

    // for Client, Timer  ....
    virtual std::shared_ptr<ServiceImpl> getImpl() const = 0;
    virtual std::shared_ptr<ImplFactory> getFactory() const = 0;
};

//TODO: IServer
//class IServer : public  IRunnable {
//public:
//    virtual ~IServer(){}
//
//    virtual void accept(IChannel::Ptr channel) = 0; //TODO:for callback 
//    virtual const int getListenPort() = 0;
//
//    virtual IChannel::Ptr getChannel(uint64_t channelId) = 0;
//};
//class ITimer : public IRunnable {
//};


} //end of namespace frame

#endif   /* FRAME_INTERFACE_H */
